<script setup lang="ts">
import { FormComponents } from "./FormComponents";
import type { FormDesignerModel, FormItemPerm } from "./FormComponentMixin";
import { initFormData, initFormRules } from "./FormInit";
import { isDisplay } from "./FormItem";
import { PropType } from "vue";
import { validateNull } from "@/utils/validate";

const props = defineProps({
  moduleId: {
    type: String,
    default: null
  },
  //组件模式，free设计模式，normal 编辑模式, read 阅读模式，disable 禁用模式
  mode: {
    type: String,
    default: "normal"
  },
  perm: {
    type: Array as PropType<FormItemPerm[]>,
    default: []
  }
});

//表单数据{}
const _value = defineModel();
//表单定义配置
const config = defineModel<FormDesignerModel>("config");
//表单规则
const formRules = ref({});
const formRef = ref(null);
const mounted = ref(false);
const moduleFormDialogRef = ref(null);
const tableListRefs = inject<Ref<object>>("tableListRefs");
const componentRefs = inject<Ref<object>>("componentRefs");
provide("moduleRef", moduleFormDialogRef);
provide("perm", props.perm);
provide("moduleId", props.moduleId);

const init = async () => {
  console.log("init", _value.value);
  if (config.value.components.length > 0) {
    const rules = initFormRules(config.value.components);
    formRules.value = rules;
    if (validateNull(_value.value)) {
      const data = await initFormData(config.value.components);
      _value.value = data;
    }
  }
  mounted.value = true;
};

const setTableRef = (el, cp) => {
  if (el) {
    if (!tableListRefs.value[cp.code]) {
      tableListRefs.value[cp.code] = el;
    }
    if (!componentRefs.value[cp.code]) {
      componentRefs.value[cp.code] = el;
    }
  }
};

const setComponentsRef = (el, cp) => {
  if (el) {
    if (!componentRefs.value[cp.code]) {
      componentRefs.value[cp.code] = el;
    }
  }
};

onMounted(() => {
  if (
    config.value &&
    Object.prototype.hasOwnProperty.call(config.value, "components") &&
    config.value.components.length > 0
  ) {
    init();
  }
});

onBeforeUnmount(() => {
  _value.value = null;
  mounted.value = false;
  tableListRefs.value = {};
  componentRefs.value = {};
});

const getFormData = () => {
  return _value.value;
};

const disableForm = () => {};

const enableForm = () => {};

const validateForm = () => {
  if (tableListRefs && tableListRefs.value) {
    Object.keys(tableListRefs.value).forEach(key => {
      if (
        tableListRefs.value[key] &&
        tableListRefs.value[key].hasOwnProperty("validate")
      ) {
        tableListRefs.value[key].validate().then(valid => {});
      }
    });
  }
  return formRef.value.validate();
};

const getFormRule = () => {
  return formRules.value;
};

const getRefs = () => {
  return componentRefs.value;
};

const handleItemValueChange = (item, val) => {
  if (
    _value.value &&
    Object.prototype.hasOwnProperty.call(_value.value, item.code)
  ) {
    _value.value[item.code] = val;
  }
};

defineExpose({
  getFormData,
  getFormRule,
  disableForm,
  enableForm,
  getRefs,
  validateForm
});
</script>

<template>
  <div class="scrollbar-container">
    <el-scrollbar v-if="mounted">
      <el-form
        ref="formRef"
        :label-width="config.conf.labelWidth"
        :size="config.conf.size"
        :label-position="config.conf.labelPosition"
        :rules="formRules"
        :model="_value"
        style="margin: 0px 5px"
      >
        <template v-for="(cp, i) in config.components" :key="cp.type + i">
          <div v-if="cp.props.isFormItem">
            <div v-if="isDisplay(props.perm, cp.code)">
              <el-form-item
                :label="cp.name"
                :required="cp.props.required"
                :class="{ 'w-form-cp-nlb': cp.props.hideLabel }"
                :prop="cp.code"
              >
                <component
                  :is="FormComponents[cp.type]"
                  :mode="props.mode"
                  :config="cp"
                  v-model="_value[cp.code]"
                  @change="handleItemValueChange"
                />
              </el-form-item>
            </div>
          </div>
          <component
            v-else-if="cp.props.isSubform"
            :ref="el => setTableRef(el, cp)"
            :is="FormComponents[cp.type]"
            :rules="formRules[cp.code]"
            :mode="props.mode"
            v-model="_value[cp.code]"
            :config="cp"
          />
          <component
            v-else
            :ref="el => setComponentsRef(el, cp)"
            :is="FormComponents[cp.type]"
            :rules="formRules"
            :mode="props.mode"
            v-model="_value"
            :config="cp"
          />
        </template>
      </el-form>
    </el-scrollbar>
  </div>
</template>

<style lang="scss" scoped>
@use "/src/assets/style/form/global";
.scrollbar-container {
  height: calc(100% - 75px);
  padding: 0px 5px;
  margin: 2px auto;
  overflow-x: hidden;

  :deep(.el-scrollbar__wrap) {
    overflow-x: hidden;
  }

  .el-scrollbar__view {
    width: 98%;
    margin: 0 auto;
    overflow-x: hidden;
  }
}
</style>
